/**
 * 图像处理核心工具类
 * 提供图片压缩、裁剪、水印、格式转换等功能
 * 基于微信小程序Canvas API实现
 */

class ImageProcessor {
  constructor() {
    this.canvas = null;
    this.ctx = null;
    this.systemInfo = wx.getSystemInfoSync();
  }

  /**
   * 初始化Canvas
   * @param {number} width - Canvas宽度
   * @param {number} height - Canvas高度
   */
  initCanvas(width, height) {
    return new Promise((resolve, reject) => {
      // 创建离屏canvas
      this.canvas = wx.createOffscreenCanvas({
        type: '2d',
        width: Math.min(width, this.systemInfo.windowWidth * 2),
        height: Math.min(height, this.systemInfo.windowHeight * 2)
      });
      
      this.ctx = this.canvas.getContext('2d');
      
      if (!this.ctx) {
        reject(new Error('Canvas初始化失败'));
        return;
      }
      
      resolve(this.canvas);
    });
  }

  /**
   * 加载图片到Canvas
   * @param {string} imagePath - 图片路径
   * @returns {Promise<Object>} 图片信息
   */
  loadImage(imagePath) {
    return new Promise((resolve, reject) => {
      wx.getImageInfo({
        src: imagePath,
        success: (res) => {
          resolve({
            width: res.width,
            height: res.height,
            path: res.path,
            type: res.type
          });
        },
        fail: reject
      });
    });
  }

  /**
   * 智能压缩图片
   * @param {Object} options - 压缩配置
   * @param {string} options.imagePath - 原图路径
   * @param {number} options.quality - 压缩质量(0-100)
   * @param {number} options.maxWidth - 最大宽度
   * @param {number} options.maxHeight - 最大高度
   * @param {string} options.format - 输出格式
   * @param {boolean} options.removeExif - 是否移除EXIF
   * @returns {Promise<string>} 压缩后图片路径
   */
  async compressImage(options) {
    const {
      imagePath,
      quality = 80,
      maxWidth = 1920,
      maxHeight = 1080,
      format = 'jpg',
      removeExif = true
    } = options;

    try {
      // 获取图片信息
      const imageInfo = await this.loadImage(imagePath);
      
      // 计算压缩后的尺寸
      let { width, height } = this.calculateResizeDimensions(
        imageInfo.width,
        imageInfo.height,
        maxWidth,
        maxHeight
      );

      // 初始化Canvas
      await this.initCanvas(width, height);

      // 绘制图片
      const img = this.canvas.createImage();
      await new Promise((resolve, reject) => {
        img.onload = resolve;
        img.onerror = reject;
        img.src = imagePath;
      });

      // 清除画布并绘制图片
      this.ctx.clearRect(0, 0, width, height);
      this.ctx.drawImage(img, 0, 0, width, height);

      // 生成压缩后的图片
      const tempFilePath = `${wx.env.USER_DATA_PATH}/compressed_${Date.now()}.${format}`;
      
      return new Promise((resolve, reject) => {
        wx.canvasToTempFilePath({
          canvas: this.canvas,
          fileType: format,
          quality: quality / 100,
          destWidth: width,
          destHeight: height,
          success: (res) => {
            resolve(res.tempFilePath);
          },
          fail: reject
        });
      });

    } catch (error) {
      throw new Error(`压缩失败: ${error.message}`);
    }
  }

  /**
   * 计算压缩后的尺寸（保持宽高比）
   * @param {number} originalWidth - 原始宽度
   * @param {number} originalHeight - 原始高度
   * @param {number} maxWidth - 最大宽度
   * @param {number} maxHeight - 最大高度
   * @returns {Object} 新的宽高
   */
  calculateResizeDimensions(originalWidth, originalHeight, maxWidth, maxHeight) {
    let width = originalWidth;
    let height = originalHeight;

    // 如果图片小于最大尺寸，不压缩
    if (width <= maxWidth && height <= maxHeight) {
      return { width, height };
    }

    // 计算缩放比例
    const widthRatio = maxWidth / width;
    const heightRatio = maxHeight / height;
    const ratio = Math.min(widthRatio, heightRatio);

    return {
      width: Math.floor(width * ratio),
      height: Math.floor(height * ratio)
    };
  }

  /**
   * 添加文字水印
   * @param {Object} options - 水印配置
   * @param {string} options.imagePath - 原图路径
   * @param {string} options.text - 水印文字
   * @param {Object} options.position - 位置配置 {x, y}
   * @param {Object} options.style - 样式配置 {fontSize, color, opacity}
   * @returns {Promise<string>} 加水印后的图片路径
   */
  async addTextWatermark(options) {
    const {
      imagePath,
      text,
      position = { x: 20, y: 20 },
      style = { fontSize: 24, color: '#ffffff', opacity: 0.7 }
    } = options;

    try {
      const imageInfo = await this.loadImage(imagePath);
      await this.initCanvas(imageInfo.width, imageInfo.height);

      const img = this.canvas.createImage();
      await new Promise((resolve, reject) => {
        img.onload = resolve;
        img.onerror = reject;
        img.src = imagePath;
      });

      // 绘制原图
      this.ctx.clearRect(0, 0, imageInfo.width, imageInfo.height);
      this.ctx.drawImage(img, 0, 0, imageInfo.width, imageInfo.height);

      // 设置水印样式
      this.ctx.font = `${style.fontSize}px Arial`;
      this.ctx.fillStyle = style.color;
      this.ctx.globalAlpha = style.opacity;
      this.ctx.textAlign = 'left';
      this.ctx.textBaseline = 'top';

      // 添加阴影效果
      this.ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
      this.ctx.shadowBlur = 2;
      this.ctx.shadowOffsetX = 1;
      this.ctx.shadowOffsetY = 1;

      // 绘制文字
      this.ctx.fillText(text, position.x, position.y);

      // 重置透明度
      this.ctx.globalAlpha = 1;

      return new Promise((resolve, reject) => {
        wx.canvasToTempFilePath({
          canvas: this.canvas,
          fileType: 'png',
          quality: 1,
          success: (res) => {
            resolve(res.tempFilePath);
          },
          fail: reject
        });
      });

    } catch (error) {
      throw new Error(`添加水印失败: ${error.message}`);
    }
  }

  /**
   * 图片裁剪
   * @param {Object} options - 裁剪配置
   * @param {string} options.imagePath - 原图路径
   * @param {Object} options.cropArea - 裁剪区域 {x, y, width, height}
   * @returns {Promise<string>} 裁剪后的图片路径
   */
  async cropImage(options) {
    const { imagePath, cropArea } = options;

    try {
      const imageInfo = await this.loadImage(imagePath);
      
      // 验证裁剪区域
      if (
        cropArea.x < 0 ||
        cropArea.y < 0 ||
        cropArea.x + cropArea.width > imageInfo.width ||
        cropArea.y + cropArea.height > imageInfo.height
      ) {
        throw new Error('裁剪区域超出图片范围');
      }

      await this.initCanvas(cropArea.width, cropArea.height);

      const img = this.canvas.createImage();
      await new Promise((resolve, reject) => {
        img.onload = resolve;
        img.onerror = reject;
        img.src = imagePath;
      });

      // 裁剪并绘制
      this.ctx.clearRect(0, 0, cropArea.width, cropArea.height);
      this.ctx.drawImage(
        img,
        cropArea.x, cropArea.y, cropArea.width, cropArea.height,
        0, 0, cropArea.width, cropArea.height
      );

      return new Promise((resolve, reject) => {
        wx.canvasToTempFilePath({
          canvas: this.canvas,
          fileType: 'png',
          quality: 1,
          success: (res) => {
            resolve(res.tempFilePath);
          },
          fail: reject
        });
      });

    } catch (error) {
      throw new Error(`裁剪失败: ${error.message}`);
    }
  }

  /**
   * 九宫格切图
   * @param {Object} options - 切图配置
   * @param {string} options.imagePath - 原图路径
   * @param {number} options.gridSize - 网格大小（默认为3）
   * @returns {Promise<Array<string>>} 9张切图的路径数组
   */
  async createGridImages(options) {
    const { imagePath, gridSize = 3 } = options;

    try {
      const imageInfo = await this.loadImage(imagePath);
      
      // 计算每个网格的尺寸
      const gridWidth = Math.floor(imageInfo.width / gridSize);
      const gridHeight = Math.floor(imageInfo.height / gridSize);
      
      const gridImages = [];

      // 创建临时目录
      const tempDir = `${wx.env.USER_DATA_PATH}/grid_${Date.now()}`;
      
      for (let row = 0; row < gridSize; row++) {
        for (let col = 0; col < gridSize; col++) {
          const x = col * gridWidth;
          const y = row * gridHeight;
          
          await this.initCanvas(gridWidth, gridHeight);

          const img = this.canvas.createImage();
          await new Promise((resolve, reject) => {
            img.onload = resolve;
            img.onerror = reject;
            img.src = imagePath;
          });

          // 绘制网格图片
          this.ctx.clearRect(0, 0, gridWidth, gridHeight);
          this.ctx.drawImage(
            img,
            x, y, gridWidth, gridHeight,
            0, 0, gridWidth, gridHeight
          );

          const gridPath = await new Promise((resolve, reject) => {
            wx.canvasToTempFilePath({
              canvas: this.canvas,
              fileType: 'jpg',
              quality: 0.9,
              success: (res) => {
                resolve(res.tempFilePath);
              },
              fail: reject
            });
          });

          gridImages.push(gridPath);
        }
      }

      return gridImages;

    } catch (error) {
      throw new Error(`九宫格切图失败: ${error.message}`);
    }
  }

  /**
   * 获取图片文件大小
   * @param {string} filePath - 文件路径
   * @returns {Promise<number>} 文件大小（KB）
   */
  async getFileSize(filePath) {
    return new Promise((resolve, reject) => {
      wx.getFileInfo({
        filePath,
        success: (res) => {
          resolve(Math.round(res.size / 1024));
        },
        fail: reject
      });
    });
  }

  /**
   * 清理Canvas资源
   */
  cleanup() {
    if (this.canvas) {
      this.canvas = null;
      this.ctx = null;
    }
  }
}

// 导出单例实例
const imageProcessor = new ImageProcessor();

module.exports = {
  ImageProcessor,
  imageProcessor
};